//实现继承
(function (window) {
    var initializing = false, fnTest = /xyz/.test(function () {
        xyz;
    }) ? /\b_super\b/ : /.*/;
    window.Class = function () {
    };
    Class.extend = function (prop) {
        var _super = this.prototype;
        initializing = true;
        var prototype = new this();
        initializing = false;
        for (var name in prop) {
            prototype[name] = typeof prop[name] == "function" &&
                typeof _super[name] == "function" && fnTest.test(prop[name]) ?
                (function (name, fn) {
                    return function () {
                        var tmp = this._super;
                        this._super = _super[name];
                        var ret = fn.apply(this, arguments);
                        this._super = tmp;

                        return ret;
                    };
                })(name, prop[name]) :
                prop[name];
        }
        function Class() {
            if (!initializing && this.__init)
                this.__init.apply(this, arguments);
        }

        Class.prototype = prototype;
        Class.prototype.constructor = Class;
        Class.extend = arguments.callee;
        return Class;
    };
})(window);
//工具类
var Utils = (function () {

    /**
     * 排列数
     * @param n
     * @param m
     * @returns {number}
     */
    function permutation(n, m) {
        var big = 1;
        for (var i = n; i > n - m; i--) {
            big *= i;
        }
        return big;
    }

    function permuteSeek(indexs, n) {
        //flag为找到位置排列的标志，m保存正在搜索哪个位置
        var flag = false, m = n;
        do {
            indexs[n]++;
            //已无位置可用
            if (indexs[n] == indexs.length){
                //重置当前位置，回退到上一个位置
                indexs[n--] = -1;
            }else if (!(function () {
                for (var i = 0; i < n; i++){
                    if (indexs[i] == indexs[n]){
                        return true;
                    }
                }
                return false;
            })()){
                //该位置未被选择
                if (m == n){
                    //当前位置搜索完成
                    flag = true;
                } else{
                    n++;
                }
            }

        } while (!flag && n >= 0)
        return flag;
    }

    /**
     * 排列结果
     * @param array
     * @param n
     * @returns {Array}
     */
    function permute(array, n) {
        var results = [];
        n = (n > array.length) ? array.length : n;
        var combinations = combine(array, n);
        var csl = combinations.length;
        for(var c = 0; c < csl; c++){
            var combination = combinations[c].split(",");
            var indexs = [];
            for (var i = 0; i < n; i++){
                indexs[i] = -1;
            }
            for (i = 0; i < n - 1; i++){
                permuteSeek(indexs, i);
            }
            while (permuteSeek(indexs, n - 1)) {
                var result = [];
                for (i = 0; i < n; i++){
                    result.push(combination[indexs[i]]);
                }
                results.push(result.join(","))
            }
        }
        return results;
    }

    /**
     * 组合数
     * @param n
     * @param m
     * @returns {number}
     */
    function combination(n, m) {
        var big = permutation(n, m);
        var small = 1;
        for (var i = 2; i <= m; i++) {
            small *= i;
        }
        return big / small;
    }

    /**
     * 组合结果
     * @param array
     * @param n
     * @returns {Array}
     */
    function combine(array, n) {
        var result = [];
        var order = [];
        n = (n > array.length) ? array.length : n;
        for (var i = 0; i <= n; i++) {
            // 注意这里order[0]=-1用来作为循环判断标识
            order[i] = i - 1;
        }
        var count = 0;
        var k = n;
        // 标志找到一个有效组合
        var flag = true;
        while (order[0] == -1) {
            // 输出符合要求的组合
            if (flag) {
                var m = [];
                for (var i = 1; i <= n; i++) {
                    var nu = array[order[i]];
                    m.push(nu);
                }
                result.push(m.join(","));
                count++;
                flag = false;
            }
            // 在当前位置选择新的数字
            order[k]++;
            // 当前位置已无数字可选，回溯
            if (order[k] == array.length) {
                order[k--] = 0;
                continue;
            }
            // 更新当前位置的下一位置的数字
            if (k < n) {
                order[++k] = order[k - 1];
                continue;
            }
            if (k == n) {
                flag = true;
            }
        }
        return result;
    }

    /**
     * 计算二维数组的组合结果
     * @param arrays 二维数组 例如：[[1],[1,2,3],[1,2]]
     * @returns {Array} 组合结果 结果：["1,1,1", "1,1,2", "1,2,1", "1,2,2", "1,3,1", "1,3,2"]
     */
    function combineArrays(arrays){
        var asl = arrays.length;
        var count = 1;
        var indexs = [];
        var results = [];
        for(var i = 0; i < asl; i++){
            indexs[i] = 0;
            count *= arrays[i].length;
        }
        for(var c = 0; c < count; c++){
            indexs = combineArraysIndexs(arrays, indexs, c, asl - 1);
            var result = [];
            for(var k = 0; k < asl; k++){
                result[k] = arrays[k][indexs[k]];
            }
            results.push(result.join(","))
        }
        return results;
    }

    /**
     * 计算二维数组排列索引
     * @param arrays 二维数组
     * @param indexs 索引
     * @param count 总数
     * @param i 第几个
     * @returns {*}
     */
    function combineArraysIndexs(arrays, indexs, count, i){
        var array = arrays[i];
        var al = array.length;
        var s = Math.floor(count / al);
        var y = count % al;
        var bl = arrays[i - 1].length;
        indexs[i] = y;
        if(s >= bl){
            combineArraysIndexs(arrays, indexs, s, --i);
        }else{
            indexs[i - 1] = s;
        }
        return indexs;
    }

    /**
     * 二维数组的组合，限制组合个数
     * @param arrays 二维数组 例如：[[1],[1,2,3],[1,2]]
     * @param n 组合个数 例如：2
     * @param placeholder 占位符 例如：-
     * @returns {Array} 结果：["1,1,-", "1,2,-", "1,3,-", "1,-,1", "1,-,2", "-,1,1", "-,1,2", "-,2,1", "-,2,2", "-,3,1", "-,3,2"]
     */
    function combineArraysLimited(arrays, n, placeholder){
        var result = [];
        var asl = arrays.length;
        if(asl >= n){
            //生成指定大小的二维数组
            var fixArrays = [[]];
            var tempArrays = [];
            var placeholders = [];
            for(var i = 0; i < asl; i++){
                tempArrays[i] = i;
                placeholders[i] = placeholder;
            }
            var combines = combine(tempArrays, n);
            var csl = combines.length;
            for(var j = 0; j < csl; j++){
                var indexs = combines[j].split(",");
                fixArrays[j] = placeholders.slice(0);
                for(var k = 0; k < n; k++){
                    var index = indexs[k];
                    fixArrays[j][index] = arrays[index];
                }
            }
            var fasl = fixArrays.length;
            for(var m = 0; m < fasl; m++){
                result = result.concat(combineArrays(fixArrays[m]));
            }
        }
        return result;
    }

    /**
     * 验证是否是url
     * @param url
     * @returns {boolean}
     */
    function isURL(url) {
        var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
        return regexp.test(url);
    }

    /**
     * 删除左右两端的空格
     * @param str
     * @returns {XML|string|void}
     */
    function trim(str) {
        return str.replace(/(^\s*)|(\s*$)/g, "");
    }

    /**
     * 代理方法
     * @param fun 要代理的方法
     * @param context 代理的对象
     * @returns {*}
     */
    function proxy(fun,context){
        var l = arguments.length;
        switch (l){
            case 0:return null;
            case 1:return fun;
            case 2:return function(){
                return fun.apply(context,arguments);
            };
            default :
                var args = [];
                for(var i=2;i<l;i++){
                    args.push(arguments[i]);
                }
                return function(){
                    var l = arguments.length;
                    var a = args.slice(0);
                    for(var i=0;i<l;i++){
                        a.push(arguments[i]);
                    }
                    return fun.apply(context,a);
                };
        }
    }

    return {
        //计算排列数
        permutation: permutation,
        //计算排列结果
        permute: permute,
        //计算组合数
        combination: combination,
        //计算组合结果
        combine: combine,
        //计算多个数组的组合结果
        combineArrays: combineArrays,
        //二维数组的组合，限制组合个数
        combineArraysLimited: combineArraysLimited,
        //验证是否是url
        isURL: isURL,
        //删除左右两端的空格
        trim: trim,
        //代理方法
        proxy: proxy
    }

})();